package org.hypnus.e.engine.config;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import org.hypnus.e.common.util.XmlUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class ServiceConfigManager {

	private static final Logger logger = LoggerFactory.getLogger(ServiceConfigManager.class);

	private Map<String, ServiceConfig> configMap = new HashMap<String, ServiceConfig>();

	private static ServiceConfigManager manager = new ServiceConfigManager();
	
	private String cfgPath ;
	
	public String getCfgPath() {
		return cfgPath;
	}

	public void setCfgPath(String cfgPath) {
		this.cfgPath = cfgPath;
	}

	protected ServiceConfigManager() {
		super();
	}

	public static ServiceConfigManager getInstance() {
		return manager;
	}

	public Map<String, ServiceConfig> getConfigMap() {
		return configMap;
	}

	private void addConfigMap(String key, ServiceConfig config) {
		configMap.put(key, config);
	}
	
	

	public void parseConfig() {

		logger.info("parse service config files start.");
		if (getCfgPath() == null) {
			throw new IllegalArgumentException(" the param of cfgPath is illegal.==>"+cfgPath);
		}

		String path = Thread.currentThread().getContextClassLoader().getResource("").getPath() + cfgPath;
		File file = new File(path);
		File[] arrFile = file.listFiles();
		for (File tmpFile : arrFile) {
			if (tmpFile.isDirectory()) {
				logger.info(tmpFile.getName() + " is not a file skip...");
				continue;
			}
			logger.info("parser " + tmpFile.getName());
			Document doc = XmlUtil.loadXmlAsDoc(tmpFile);
			Element root = doc.getDocumentElement();
			String key = root.getAttribute("name");
			ServiceConfig config = new ServiceConfig();
			config.setName(key);
			config.setExtend(root.getAttribute("extends"));

			addConfigMap(key, config);

			NodeList elt = root.getElementsByTagName("service");
			for (int i = 0; i < elt.getLength(); i++) {
				Element tmpElt = (Element) elt.item(i);
				ServiceNode node = parseService(tmpElt);
				config.addNode(node);
			}
		}
		logger.info("parse service config files end.");
	}

	private ServiceNode parseService(Element elt) {
		logger.info("parse service node ==>" + elt.getAttribute("name"));
		ServiceNode node = new ServiceNode();
		node.setName(elt.getAttribute("name"));
		node.setHandler(elt.getAttribute("handler")) ;
		logger.info("parse binding node ");
		NodeList lstBdg = elt.getElementsByTagName("binding");
		if (lstBdg.getLength() > 0) {
			Element tmpElt = (Element) lstBdg.item(0);
			BindingNode tmp = parseBinding(tmpElt, "in") ;
			if(tmp!=null){
				node.addBdgNode(tmp);
			}
			tmp = parseBinding(tmpElt, "out") ;
			if(tmp!=null){
				node.addBdgNode(tmp);
			}
		}

		logger.info("parse forward node ");
		NodeList lstFrd = elt.getElementsByTagName("forward");
		for (int i = 0, len = lstFrd.getLength();  len>0 && i < len; i++) {
			node.addFrdNode(parseForward((Element) lstFrd.item(i)));
		}
		return node;
	}

	private BindingNode parseBinding(Element elt, String strChild) {
		NodeList lstin = elt.getElementsByTagName(strChild);
		BindingNode tmpNode = null;
		if (lstin != null && lstin.getLength()>0) {
			tmpNode = new BindingNode();
			tmpNode.setBindingType(strChild);
			for (int i = 0, len = lstin.getLength(); i < len; i++) {
				Element tmpElt = (Element) lstin.item(i) ;
				tmpNode.addExp(new ExpressionNode(tmpElt.getAttribute("name"), tmpElt.getAttribute("expression")));
			}
		}
		return tmpNode;
	}

	private ForwardNode parseForward(Element elt) {
		ForwardNode node = new ForwardNode();
		node.setExpression(elt.getAttribute("expression"));
		node.setTarget(elt.getAttribute("target"));
		return node;
	}

	public ServiceConfig getServiceConfig(String key) {
		ServiceConfig config = configMap.get(key);
		if (config == null) {
			throw new IllegalArgumentException("can't find service config by serviceid ==>" + key);
		}
		return config;
	}

	public static void main(String[] args) {
		ServiceConfigManager manager = new ServiceConfigManager();
		manager.setCfgPath("org/hypnus/e/engine/test") ;
		manager.parseConfig();
	}
}
